﻿using System;
using System.Diagnostics;
using System.Drawing;

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;

namespace vis_client
{
	class MainWindow : GameWindow
	{
		protected Stopwatch _Stopwatch = new Stopwatch();
		protected int _NumFrames = 0;
		protected bool _FrameSizeChanged = false;

		public MainWindow()
		{
			int x = 0;
			int y = 0;
			int width = 640;
			int height = 640;
			this.Bounds = new Rectangle(x, y, width, height);

			this.UpdateTransform();

			SimData.FrameSizeChanged += new MethodInvoker(SimData_FrameSizeChanged);
		}

		protected override void OnKeyPress(KeyPressEventArgs e)
		{
			base.OnKeyPress(e);

			if (e.KeyChar == 'f' || e.KeyChar == 'F')
			{
				if (this.WindowState == OpenTK.WindowState.Fullscreen)
					this.WindowState = OpenTK.WindowState.Normal;
				else
					this.WindowState = OpenTK.WindowState.Fullscreen;
			}
			else if (e.KeyChar == 'q' || e.KeyChar == 'Q')
			{
				this.Close();
			}
		}

		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);

			GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
			_Stopwatch.Start();
		}

		protected override void OnResize(EventArgs e)
		{
			base.OnResize(e);
			this.UpdateTransform();
		}

		protected override void OnUpdateFrame(FrameEventArgs e)
		{
			base.OnUpdateFrame(e);

			if (Keyboard[Key.Escape])
				this.Exit();
		}

		protected override void OnRenderFrame(FrameEventArgs e)
		{
			base.OnRenderFrame(e);

			if (_FrameSizeChanged)
			{
				this.UpdateTransform();
				_FrameSizeChanged = false;
			}

			GL.Clear(ClearBufferMask.ColorBufferBit);

			SimData data = SimData.GetCurData();
			if (data != null &&
				data.FrameWidth > 0 && data.FrameWidth > 0)
			{
				GL.DrawPixels(data.FrameWidth, data.FrameHeight, 
					PixelFormat.Rgba, PixelType.UnsignedByte, data.Frame);
			}

			SwapBuffers();

			_NumFrames++;
			if (_NumFrames % 100 == 0)
			{
				double avgFrameTime = _Stopwatch.ElapsedMilliseconds / 100.0;
				Debug.WriteLine("Drawing " + (1000.0 / avgFrameTime).ToString("n4") + " frames per second");
				_Stopwatch.Reset();
				_Stopwatch.Start();
			}
		}

		protected void UpdateTransform()
		{
			SimData data = SimData.GetCurData();
			if (data != null)
			{
				GL.PixelZoom((float)this.ClientRectangle.Width / (float)data.FrameWidth,
								(float)this.ClientRectangle.Height / (float)data.FrameHeight);
				GL.RasterPos2(0, 0);
				GL.MatrixMode(MatrixMode.Projection);
				GL.LoadIdentity();
				GL.Ortho(0.0, data.FrameWidth, 0.0, data.FrameHeight, -1.0, 1.0);
				GL.MatrixMode(MatrixMode.Modelview);
			}
		}

		private void SimData_FrameSizeChanged()
		{
			_FrameSizeChanged = true;
		}


		[STAThread]
		static void Main()
		{
			ServerConnection conn = new ServerConnection("tessy.umcs.maine.edu", 12345);
			if (conn.IsConnected)
			{
				MainWindow vis = new MainWindow();
				vis.Run();
			}
			conn.Close();
		}
	}
}
